#pragma once

namespace MeshConverter {
	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Button^  button1;				//for convert button
	private: System::Windows::Forms::RadioButton^  radioButton1;	//for convex meshes
	private: System::Windows::Forms::RadioButton^  radioButton2;	//for triangle meshes
	private: System::Windows::Forms::Label^  label1;
	private: System::String^	selectedFile;							//the selected file
	private: System::String^	selectedOutput;
	private: System::String^	fileName;			//the selected file name without file path
	private: System::Windows::Forms::Button^  button2;				//for the select file
	private: System::Windows::Forms::OpenFileDialog^  openFileDialog1;
	private: System::Windows::Forms::Button^  button3;
	private: System::Windows::Forms::FolderBrowserDialog^  folderBrowserDialog1;
	private: System::Windows::Forms::ProgressBar^  progressBar1;

	private: System::ComponentModel::IContainer^  components;
	protected:

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->button1 = (gcnew System::Windows::Forms::Button());
			this->radioButton1 = (gcnew System::Windows::Forms::RadioButton());
			this->radioButton2 = (gcnew System::Windows::Forms::RadioButton());
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->button2 = (gcnew System::Windows::Forms::Button());
			this->openFileDialog1 = (gcnew System::Windows::Forms::OpenFileDialog());
			this->button3 = (gcnew System::Windows::Forms::Button());
			this->folderBrowserDialog1 = (gcnew System::Windows::Forms::FolderBrowserDialog());
			this->progressBar1 = (gcnew System::Windows::Forms::ProgressBar());
			this->SuspendLayout();
			//
			// button1
			//
			this->button1->Location = System::Drawing::Point(108, 112);
			this->button1->Name = L"button1";
			this->button1->Size = System::Drawing::Size(75, 23);
			this->button1->TabIndex = 0;
			this->button1->Text = L"Convert";
			this->button1->UseVisualStyleBackColor = true;
			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
			//
			// radioButton1
			//
			this->radioButton1->AutoSize = true;
			this->radioButton1->Location = System::Drawing::Point(158, 36);
			this->radioButton1->Name = L"radioButton1";
			this->radioButton1->Size = System::Drawing::Size(89, 17);
			this->radioButton1->TabIndex = 1;
			this->radioButton1->TabStop = true;
			this->radioButton1->Text = L"Convex mesh";
			this->radioButton1->UseVisualStyleBackColor = true;
			this->radioButton1->Click += gcnew System::EventHandler(this, &Form1::radioButton_Click);
			//
			// radioButton2
			//
			this->radioButton2->AutoSize = true;
			this->radioButton2->Location = System::Drawing::Point(158, 60);
			this->radioButton2->Name = L"radioButton2";
			this->radioButton2->Size = System::Drawing::Size(91, 17);
			this->radioButton2->TabIndex = 2;
			this->radioButton2->TabStop = true;
			this->radioButton2->Text = L"Triangle mesh";
			this->radioButton2->UseVisualStyleBackColor = true;
			this->radioButton2->Click += gcnew System::EventHandler(this, &Form1::radioButton_Click);
			//
			// label1
			//
			this->label1->AutoSize = true;
			this->label1->Location = System::Drawing::Point(12, 9);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(60, 13);
			this->label1->TabIndex = 3;
			this->label1->Text = L"Description";
			//
			// button2
			//
			this->button2->Location = System::Drawing::Point(15, 111);
			this->button2->Name = L"button2";
			this->button2->Size = System::Drawing::Size(75, 23);
			this->button2->TabIndex = 4;
			this->button2->Text = L"Select file";
			this->button2->UseVisualStyleBackColor = true;
			this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
			//
			// openFileDialog1
			//
			this->openFileDialog1->DefaultExt = L"mesh";
			this->openFileDialog1->FileName = L"select something";
			this->openFileDialog1->Filter = L"mesh files (*.mesh)|*.mesh";
			//
			// button3
			//
			this->button3->Location = System::Drawing::Point(209, 112);
			this->button3->Name = L"button3";
			this->button3->Size = System::Drawing::Size(129, 23);
			this->button3->TabIndex = 5;
			this->button3->Text = L"Select Out Directory";
			this->button3->UseVisualStyleBackColor = true;
			this->button3->Click += gcnew System::EventHandler(this, &Form1::button3_Click);
			//
			// progressBar1
			//
			this->progressBar1->Location = System::Drawing::Point(1, 141);
			this->progressBar1->Maximum = 4;
			this->progressBar1->Name = L"progressBar1";
			this->progressBar1->Size = System::Drawing::Size(374, 23);
			this->progressBar1->Step = 1;
			this->progressBar1->TabIndex = 6;
			this->progressBar1->Visible = true;
			//
			// Form1
			//
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(375, 166);
			this->Controls->Add(this->progressBar1);
			this->Controls->Add(this->button3);
			this->Controls->Add(this->button2);
			this->Controls->Add(this->label1);
			this->Controls->Add(this->radioButton2);
			this->Controls->Add(this->radioButton1);
			this->Controls->Add(this->button1);
			this->Name = L"Form1";
			this->Text = L"Ogre 2 NXS Converter";
			this->ResumeLayout(false);
			this->PerformLayout();
		}
#pragma endregion

	private: System::Void radioButton_Click(System::Object^  sender, System::EventArgs^  e)
		{
			if(radioButton1->Checked)
				label1->Text = L"Convex meshes are for dynamic bodies";
			else if(radioButton2->Checked)
				label1->Text = L"Triangle meshes are for static bodies bodies";
		}
	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
			 {
				 if(selectedFile == System::String::Empty)
				 {
					 label1->Text = L"Select a file to convert first!";
					 return;
				 }
				 if(selectedOutput == System::String::Empty)
				 {
					label1->Text = L"Select a folder!";
					 return;
				 }

				label1->Text = L"Exporting mesh...";
				System::String ^_Output = nullptr;
				System::String ^_Error = nullptr;
				ExecuteShellCommand("OgreXMLConverter ","\""+selectedFile+"\" "
					+"temp\\"+fileName+".mesh.xml", _Output, _Error);
				System::String^ meshType;
				if(radioButton1->Checked)
					meshType = L" convex ";
				else if(radioButton2->Checked)
					meshType = L" triangle ";
				progressBar1->Value = 0;
				ExecuteShellCommand("ogrexmltoflower",meshType+"temp\\"+fileName+".mesh.xml", _Output, _Error);
				progressBar1->PerformStep();
				ExecuteShellCommand("Flour"," convert temp\\"+fileName+".flower", _Output, _Error);
				progressBar1->PerformStep();
				ExecuteShellCommand("COPY ","temp\\"+fileName+".nxs "+"\""+selectedOutput+"\"", _Output, _Error);
				progressBar1->PerformStep();
				ExecuteShellCommand("DEL /Q ","temp\\"+fileName+".flower "+"temp\\"+fileName+".mesh.xml "+"temp\\"+fileName+".nxs", _Output, _Error);
				progressBar1->PerformStep();
				//System::Diagnostics::Process::Start("OgreXMLConverter");

				label1->Text = fileName+" converted successfully";
			 }
	private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e)
			 {
				System::Windows::Forms::DialogResult result = openFileDialog1->ShowDialog();

				if ( result == System::Windows::Forms::DialogResult::OK )
				{
					selectedFile = openFileDialog1->FileName;
					if(selectedFile != System::String::Empty)
					{
						fileName = retrieveFileName(selectedFile);
						//label1->Text = L"File selected";
						label1->Text = "OgreXMLConverter "+selectedFile;
					}
				}
			 }

			/// <summary>
	/// Execute a shell command
	/// </summary>
	/// <param name="_FileToExecute">File/Command to execute</param>
	/// <param name="_CommandLine">Command line parameters to pass</param>
	/// <param name="_outputMessage">returned string value after executing shell command</param>
	/// <param name="_errorMessage">Error messages generated during shell execution</param>
	private: void ExecuteShellCommand(System::String ^_FileToExecute, System::String ^_CommandLine, System::String ^%_outputMessage, System::String ^%_errorMessage)
	{
		// Set process variable
		// Provides access to local and remote processes and enables you to start and stop local system processes.
		System::Diagnostics::Process ^_Process = nullptr;
		try
		{
			_Process = gcnew System::Diagnostics::Process();

			// invokes the cmd process specifying the command to be executed.
			System::String ^_CMDProcess = System::String::Format(System::Globalization::CultureInfo::InvariantCulture, "{0}\\cmd.exe", gcnew array<System::Object^> { Environment::SystemDirectory });

			// pass executing file to cmd (Windows command interpreter) as a arguments
			// /C tells cmd that we want it to execute the command that follows, and then exit.
			System::String ^_Arguments = System::String::Format(System::Globalization::CultureInfo::InvariantCulture, "/C {0}", gcnew array<System::Object^> { _FileToExecute });

			// pass any command line parameters for execution
			if (_CommandLine != nullptr && _CommandLine->Length > 0)
			{
				_Arguments += System::String::Format(System::Globalization::CultureInfo::InvariantCulture, " {0}", gcnew array<System::Object^> { _CommandLine, System::Globalization::CultureInfo::InvariantCulture });
			}

			// Specifies a set of values used when starting a process.
			System::Diagnostics::ProcessStartInfo ^_ProcessStartInfo = gcnew System::Diagnostics::ProcessStartInfo(_CMDProcess, _Arguments);
			// sets a value indicating not to start the process in a new window.
			_ProcessStartInfo->CreateNoWindow = true;
			// sets a value indicating not to use the operating system shell to start the process.
			_ProcessStartInfo->UseShellExecute = false;
			// sets a value that indicates the output/input/error of an application is written to the Process.
			_ProcessStartInfo->RedirectStandardOutput = true;
			_ProcessStartInfo->RedirectStandardInput = true;
			_ProcessStartInfo->RedirectStandardError = true;
			_Process->StartInfo = _ProcessStartInfo;

			// Starts a process resource and associates it with a Process component.
			_Process->Start();

			// Instructs the Process component to wait indefinitely for the associated process to exit.
			_errorMessage = _Process->StandardError->ReadToEnd();
			_Process->WaitForExit();

			// Instructs the Process component to wait indefinitely for the associated process to exit.
			_outputMessage = _Process->StandardOutput->ReadToEnd();
			_Process->WaitForExit();
		}
		catch (Win32Exception ^_Win32Exception)
		{
			// Error
			Console::WriteLine("Win32 Exception caught in process: {0}", _Win32Exception->ToString());
		}
		catch (Exception ^_Exception)
		{
			// Error
			Console::WriteLine("Exception caught in process: {0}", _Exception->ToString());
		}
		finally
		{
			// close process and do cleanup
			_Process->Close();
			delete _Process;
			_Process = nullptr;
		}
	}
private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e)
		 {
			System::Windows::Forms::DialogResult result = folderBrowserDialog1->ShowDialog();
			if ( result == System::Windows::Forms::DialogResult::OK )
			{
				selectedOutput = folderBrowserDialog1->SelectedPath;
			}
		 }

		 private: System::String^ retrieveFileName(System::String^ filePath)
				  {
					  System::String^ fileName = nullptr;
					  int pos = filePath->LastIndexOf('\\');
					  if(pos != -1)
						fileName  = filePath->Substring(pos+1);

					  if(fileName != nullptr)
					  {
						pos = fileName->LastIndexOf('.');
						int amount =fileName->Length-(fileName->Length - (pos));
						fileName = fileName->Substring(0,amount);
					  }

					  return fileName;
				  }
};
}